/* The file is saved in UTF-8 codepage.
 * Check: «Stereotype», Section mark-§, Copyright-©, Alpha-α, Beta-β, Smile-☺
 */
package cz.pecinovsky.english.lootp._134_;



import cz.pecinovsky.english.lootp.manager.CanvasManager_Envelope.CanvasManager;

import cz.pecinovsky.english.lootp.utility.IO;

import cz.pecinovsky.english.lootp._134_.IRingFactory_140_.     IRingFactory;
import cz.pecinovsky.english.lootp._134_.Ring_134_.            Ring;
import cz.pecinovsky.english.lootp._134_.StavitelOkruhů_134_.   StavitelOkruhů;


//import cz.pecinovsky.english.lootp._134_.RingFactory_140_.RingFactory;
////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ End of ignored starting test - place for imports +++++
//%I+
//
//import cz.pecinovsky.english.lootp.manager.CanvasManager_Envelope.CanvasManager;
//%I-

import cz.pecinovsky.english.lootp.utility.NamedColor;
import cz.pecinovsky.english.lootp.utility.Position;
import cz.pecinovsky.english.lootp.utility.Direction8;

//%X+ xxxxx Start of the ovejumped text with declaration of the envelope xxxxx
/*******************************************************************************
 *<pre>
 * Předchozí:   Není - toto_je_nově_definovaná_třída
 *              Ttt v projektu Ppp
 * Následující: Prozatím není
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */
public class RingFactory_140_
{    private RingFactory_140_() {}   static
////////////////////////////////////////////////////////////////////////////////
//%X- ----- End of the ovejumped text with declaration of the envelope -----


/*******************************************************************************
 * Instance třídy {@code RingFactory} představují továrny, které jsou schopny
 * na požádání "vyrobit" obdélníkový okruh.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
public class RingFactory implements IRingFactory
{
//== CONSTANT CLASS ATTRIBUTES =================================================

    /** Správce plátna, na němž bude cesta zobrazena. */
    CanvasManager CM = CanvasManager.getInstance();



//== VARIABLE CLASS ATTRIBUTES =================================================
//== STATIC CONSTRUCTOR (CLASS INITIALIZER, STATIC INICITALIZING BLOCK) ========
//== CONSTANT INSTANCE ATTRIBUTES ==============================================

    /** Políčková šířka okruhů, tj. počet zabraných columnSize. */
    private final int columnSize;

    /** Políčková výška okruhů, tj. počet zabraných řádků. */
    private final int rowSize;

    /** Směr, která se vyráží z výchozí pozice. */
    private final Direction8 direction;



//== VARIABLE INSTANCE ATTRIBUTES ==============================================

     /** Implicitní color vytvářených okruhů. */
     private NamedColor defaultColor = NamedColor.BLACK;



//== CLASS GETTERS AND SETTERS =================================================
//== OTHER NON-PRIVATE CLASS METHODS ===========================================

//##############################################################################
//== CONSTUCTORS AND FACTORY METHODS ===========================================

    /***************************************************************************
     * Vytvoří nový obdélníkový okruh se zadanou počtem polí na šířku i výšku
     * a se zadaným směrem, jímž se vyráží z vvýchozí pozice, která je vždy
     * v levém horním rohu vytvořeného okruhu.
     *
     * @param columnSize Políčková šířka okruhů, tj. počet zabraných sloupců
     * @param rowSize   Políčková výška okruhů, tj. počet zabraných řádků
     * @param direction    Směr, která se vyráží z výchozí pozice, má smysl pouze
     *                {@link Direction8.EAST} nebo {@link Direction8.SOUTH}
     */
    public RingFactory(int columnSize, int rowSize, Direction8 direction)
    {
        this.columnSize = columnSize;
        this.rowSize    = rowSize;
        this.direction  = direction;
    }



//== ABSTRACT METHODS ==========================================================
//== INSTANCE GETTERS AND SETTERS ==============================================

    /***************************************************************************
     * Nastaví implicitní barvu vytvářených okruhů.
     *
     * @param color Nastavovaná implicitní color
     * @return Dříve nastavená implicitní color
     */
    @Override
    public NamedColor setDefaultColor(NamedColor color)
    {
        NamedColor old = defaultColor;
        defaultColor = color;
        return old;
    }


    /***************************************************************************
     * Vrátí počet sloupců, které daný okruh zabere.
     *
     * @return Počet sloupců okruhu
     */
    public int getColumnSize()
    {
        return columnSize;
    }


    /***************************************************************************
     * Vrátí počet řádků, které daný okruh zabere.
     *
     * @return Počet řádků okruhu
     */
    public int getRowSize()
    {
        return rowSize;
    }



//== OTHER NON-PRIVATE INSTANCE METHODS ========================================

    /***************************************************************************
     * Vytvoří okruh implicitní barvy se startovním polem na zadané pozici.
     *
     * @param startPosition Position startovního pole vytvářeného okruhu
     * @return Vytvořený okruh
     */
    @Override
    public Ring createRing(Position startPosition)
    {
        return createRing(startPosition, defaultColor);
    }


    /***************************************************************************
     * Vytvoří okruh zadané barvy se startovním polem na zadané pozici.
     *
     * @param startPosition Position startovního pole vytvářeného okruhu
     * @param color       NamedColor vytvářeného okruhu
     * @return Vytvořený okruh
     */
    @Override
    public Ring createRing(Position startPosition, NamedColor color)
    {
        StavitelOkruhů builder = new StavitelOkruhů(startPosition, color);
        builder.zahajNa(direction);
        if (direction == Direction8.SOUTH) {
            completeRing(builder, rowSize-1, columnSize, rowSize, columnSize-1);
        }
        else {
            completeRing(builder, columnSize-1, rowSize, columnSize, rowSize-1);
        }
        return builder.getOkruh();
    }


    /***************************************************************************
     * Prostřednictvím zadaného stavitele dotvoří okruh zadaných rozměrů
     * přičemž direction pohybu po vytvářeném okruhu je odvozen z atributu
     * {@link #direction}.
     *
     * @param builder Stavitel, který začal stavět zadaný okruh
     * @param sizes  Počet průběžných polí, která se mají položit
     *                 v jednotlivých směrech
     */
    private void completeRing(StavitelOkruhů builder, int... sizes)
    {
        if (sizes.length != 4) {
            throw new IllegalArgumentException(
                    "\nMusí být zadány právě čtyři rozměry");
        }
        Direction8 currentDirection = direction;
        for (int rozměr : sizes) {
            for (int i=1;   i < rozměr;   i++) {
                builder.pokračujNa(currentDirection);
            }
            if (direction == Direction8.SOUTH) {
                currentDirection = currentDirection.leftFace();
            } else {
                currentDirection = currentDirection.rightFace();
            }
        }
        //Musím direction otočit zpět, protože ještě nezahýbám
        if (direction == Direction8.SOUTH) {
            currentDirection = currentDirection.rightFace();
        } else {
            currentDirection = currentDirection.leftFace();
        }
        builder.closeTo(currentDirection);
    }



//== PRIVATE AND AUXILIARY CLASS METHODS =======================================
//== PRIVATE AND AUXILIARY INSTANCE METHODS ====================================
//== EMBEDDED TYPES AND INNER CLASSES ==========================================
//== TESTING CLASSES AND METHODS ===============================================
//
//    /***************************************************************************
//     * Test method.
//     */
//    public static void test()
//    {
//        RingFactory inst = new RingFactory();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main(String[] args)  {  test();  }
    }

//%%- ---- Start of the ovejumped text with closing of the envelope ----
////////////////////////////////////////////////////////////////////////////////
//== TESTING CLASSES AND METHODS ===============================================
//Není-li třída testovací, následující dvě metody se smažou

    /***************************************************************************
     * Test method.
     */
    public static void test()
    {
        Direction8 direction = Direction8.SOUTH;
        CanvasManager CM = CanvasManager.getInstance();

        for (int i=2;   i <= 6;   i++)  {
            RingFactory tk = new RingFactory(i, i, direction);
            Ring o = tk.createRing(new Position(0,0), NamedColor.BLACK);
            CM.add(o);
            IO.inform("Vytvořen okruh \n" + o);
            CM.remove(o);
            direction = (direction  == Direction8.SOUTH)  ?  Direction8.EAST
                                         :  Direction8.SOUTH;
        }
        System.exit(0);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main(String[] args)  { test(); }
}
